class Pagination {
  constructor(root, options) {
    this.__root = root;
    this.__options = options;
    this.__current = this.__options.curr;
    this.__items = [];

    this.init();
  }

  init() {
    this.__root.classList.add("pagination");
    this.__render();
  }

  destroy() {
    this.__root.classList.remove("pagination");
    this.__removeItems();
  }

  __removeItems() {
    this.__items.forEach((item) => item.remove());
    this.__items = [];
  }

  __render() {
    this.__removeItems();

    const isCollapsed = this.__options.slots <= 6;
    const slots = Math.min(this.__options.slots, this.__options.total);
    const ellipsisPos = [];
    let i, showFirst, showLast;

    // Center active page in middle of pagination
    let start = this.__current - Math.round(this.__options.slots / 2) + 1;

    // If pagination values exceed the expected range,
    // Fix the range on start or end
    const overflow = start + slots - 1 - this.__options.total;
    if (overflow > 0) start -= overflow;
    if (start <= 0) start -= start - 1;

    // Set end slot
    const end = start + slots - 1;

    // Check if it should have ellipsis and define sllipsis position
    const hasEllipsisLeft = start > 1;
    const hasEllipsisRright = end < this.__options.total;
    if (hasEllipsisLeft) ellipsisPos.push(isCollapsed ? start : start + 1);
    if (hasEllipsisRright) ellipsisPos.push(isCollapsed ? end : end - 1);

    for (i = start; i <= end; i++) {
      showFirst = !isCollapsed && i == start && hasEllipsisLeft;
      showLast = !isCollapsed && i == end && hasEllipsisRright;

      if (showFirst) {
        this.__renderElement(1);
      } else if (ellipsisPos.includes(i)) {
        this.__renderElement("...");
      } else if (showLast) {
        this.__renderElement(this.__options.total);
      } else {
        this.__renderElement(i);
      }
    }
  }

  __renderElement(value) {
    const isPage = typeof value === "number";
    const el = document.createElement(isPage ? "button" : "span");
    el.classList.add("pagination__item");
    el.textContent = value;

    if (isPage) {
      el.classList.add("pagination__item--button");
      el.addEventListener("click", () => {
        this.__current = value;
        this.__options.onChange(value);
        this.__render();
      });

      if (value == this.__current) {
        el.classList.add("active");
      }
    }

    return this.__items.push(this.__root.appendChild(el));
  }
}

(() => {
  new Pagination(document.querySelector("#pagination-1"), {
    curr: 1,
    slots: 5,
    total: 8,
    onChange: (page) => console.log("Pagination 1 changed to", page),
  });

  new Pagination(document.querySelector("#pagination-2"), {
    curr: 10,
    slots: 8,
    total: 20,
    onChange: (page) => console.log("Pagination 2 thanged to", page),
  });
})();
